<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>五子棋小游戏</title>
    <style>
        :root {
            --primary-color: #8B4513;
            --board-color: #D2B48C;
            --highlight-color: #E2C78C;
            --shadow-color: rgba(0, 0, 0, 0.25);
        }
        
        body {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
            font-family: "Microsoft YaHei", Arial, sans-serif;
            transition: background 0.5s ease;
            overflow: hidden;
        }
        
        .container {
            position: relative;
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        
        #gameInfo {
            margin-bottom: 20px;
            font-size: 24px;
            font-weight: bold;
            color: #333;
            text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
            transition: all 0.3s ease;
        }
        
        .canvas-container {
            position: relative;
            box-shadow: 0 10px 30px rgba(0,0,0,0.15);
            border-radius: 5px;
            transition: transform 0.3s ease;
        }
        
        .canvas-container:hover {
            transform: translateY(-5px);
        }
        
        #gameCanvas {
            border: 10px solid var(--primary-color);
            border-radius: 5px;
            background: radial-gradient(circle, var(--highlight-color) 0%, var(--board-color) 100%);
            cursor: pointer;
        }
        
        .controls {
            display: flex;
            justify-content: center;
            gap: 20px;
            margin-top: 20px;
        }
        
        button {
            padding: 10px 20px;
            font-size: 16px;
            font-weight: bold;
            color: #fff;
            background: linear-gradient(145deg, #a05b19, #8B4513);
            border: none;
            border-radius: 50px;
            cursor: pointer;
            box-shadow: 0 4px 8px rgba(0,0,0,0.15);
            transition: all 0.3s ease;
            outline: none;
        }
        
        button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 12px rgba(0,0,0,0.2);
            background: linear-gradient(145deg, #b06b29, #9B5523);
        }
        
        button:active {
            transform: translateY(1px);
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        
        .game-over-dialog {
            display: none;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(255,255,255,0.95);
            padding: 30px;
            border-radius: 15px;
            box-shadow: 0 15px 35px rgba(0,0,0,0.2);
            text-align: center;
            z-index: 1000;
            backdrop-filter: blur(5px);
            border: 2px solid rgba(255,255,255,0.1);
            animation: fadeIn 0.3s ease-out;
        }
        
        @keyframes fadeIn {
            from { opacity: 0; transform: translate(-50%, -60%); }
            to { opacity: 1; transform: translate(-50%, -50%); }
        }
        
        .game-over-dialog p {
            font-size: 24px;
            margin-bottom: 20px;
            color: #333;
        }
        
        .game-over-dialog button {
            margin-top: 10px;
        }
        
        #currentPositionMarker {
            position: absolute;
            width: 10px;
            height: 10px;
            background-color: rgba(255, 0, 0, 0.7);
            border-radius: 50%;
            transform: translate(-50%, -50%);
            pointer-events: none;
            display: none;
        }
        
        .history-container {
            position: absolute;
            top: 10px;
            right: 10px;
            background: rgba(255,255,255,0.8);
            padding: 10px;
            border-radius: 10px;
            max-height: 300px;
            overflow-y: auto;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
        }
        
        .history-move {
            padding: 5px 0;
            font-size: 14px;
            border-bottom: 1px solid #eee;
        }
        
        /* 响应式设计 */
        @media (max-width: 600px) {
            #gameCanvas {
                width: 90vw;
                height: 90vw;
                max-width: 450px;
                max-height: 450px;
            }
            
            .controls {
                flex-direction: column;
                gap: 10px;
                align-items: center;
            }
            
            button {
                width: 100%;
                max-width: 200px;
            }
        }
        
        /* 无障碍支持 */
        .visually-hidden {
            position: absolute;
            width: 1px;
            height: 1px;
            margin: -1px;
            padding: 0;
            overflow: hidden;
            clip: rect(0, 0, 0, 0);
            border: 0;
        }
    </style>
</head>
<body>
    <div class="container">
        <div id="gameInfo" role="status" aria-live="polite">当前轮到黑棋</div>
        <div class="canvas-container">
            <canvas id="gameCanvas" width="450" height="450" tabindex="0" aria-label="五子棋棋盘" role="application"></canvas>
            <div id="currentPositionMarker"></div>
        </div>
        <div class="controls">
            <button id="undoButton" onclick="undoMove()" aria-label="悔棋">悔棋</button>
            <button id="saveButton" onclick="saveGame()" aria-label="保存游戏">保存游戏</button>
            <button id="loadButton" onclick="loadGame()" aria-label="读取游戏">读取游戏</button>
        </div>
    </div>
    
    <div id="gameOverDialog" class="game-over-dialog" role="dialog" aria-modal="true" aria-labelledby="gameOverMessage">
        <p id="gameOverMessage"></p>
        <button onclick="resetGame()" aria-label="重新开始游戏">重新开始</button>
    </div>
    
    <div id="moveHistory" class="history-container" style="display: none;">
        <h3>棋局记录</h3>
        <div id="moveList"></div>
    </div>
    
    <audio id="moveSound" preload="auto">
        <source src="data:audio/mpeg;base64,SUQzBAAAAAABEVRYWFgAAAAtAAADY29tbWVudABCaWdTb3VuZEJhbmsuY29tIC8gTGFTb25vdGhlcXVlLm9yZwBURU5DAAAAHQAAA1N3aXRjaCBQbHVzIMKpIE5DSCBTb2Z0d2FyZQBUSVQyAAAABgAAAzIyMzUAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAAAAD/80DEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQsRbAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQMSkAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" type="audio/mpeg">
    </audio>
    <audio id="winSound" preload="auto">
        <source src="data:audio/mpeg;base64,SUQzBAAAAAABEVRYWFgAAAAtAAADY29tbWVudABCaWdTb3VuZEJhbmsuY29tIC8gTGFTb25vdGhlcXVlLm9yZwBURU5DAAAAHQAAA1N3aXRjaCBQbHVzIMKpIE5DSCBTb2Z0d2FyZQBUSVQyAAAABgAAAzIyMzUAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAAAAD/80DEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQsRbAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQMSkAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV" type="audio/mpeg">
    </audio>
    <script>
        // 获取DOM元素
        const canvas = document.getElementById('gameCanvas');
        const ctx = canvas.getContext('2d');
        const gameInfo = document.getElementById('gameInfo');
        const gameOverDialog = document.getElementById('gameOverDialog');
        const gameOverMessage = document.getElementById('gameOverMessage');
        const moveSound = document.getElementById('moveSound');
        const winSound = document.getElementById('winSound');
        const positionMarker = document.getElementById('currentPositionMarker');
        const moveList = document.getElementById('moveList');
        
        // 游戏常量
        const GRID_SIZE = 15;
        const CELL_SIZE = canvas.width / GRID_SIZE;
        const BOARD_SIZE = canvas.width;
        
        // 游戏状态变量
        let board = Array.from({ length: GRID_SIZE }, () => Array(GRID_SIZE).fill(0));
        let currentPlayer = 1; // 1: 黑棋, -1: 白棋
        let gameOver = false;
        let moveHistory = []; // 记录每一步的落子位置
        let currentPosition = { x: -1, y: -1 }; // 当前光标位置
        let lastMoveTime = 0; // 用于动画效果
        let frames = 0; // 帧计数器，用于性能监控
        let startTime = performance.now();
        
        // 渲染相关变量
        let animationFrameId = null;
        let particles = []; // 特效粒子
        
        // 初始化函数
        function init() {
            // 调整画布大小为响应式
            resizeCanvas();
            window.addEventListener('resize', resizeCanvas);
            
            // 添加事件监听器
            canvas.addEventListener('click', handleClick);
            canvas.addEventListener('mousemove', handleMouseMove);
            canvas.addEventListener('mouseout', () => {
                positionMarker.style.display = 'none';
            });
            canvas.addEventListener('keydown', handleKeydown);
            
            // 启动游戏循环
            startGameLoop();
            
            // 尝试从本地存储加载游戏
            checkSavedGame();
        }
        
        // 响应式画布调整
        function resizeCanvas() {
            const containerWidth = Math.min(window.innerWidth * 0.9, 600);
            const size = Math.floor(containerWidth - 20); // 减去边框
            
            canvas.width = size;
            canvas.height = size;
            
            // 重新计算单元格大小
            const CELL_SIZE = size / GRID_SIZE;
            
            // 重绘棋盘
            drawBoard();
            drawAllPieces();
        }
        
        // 游戏主循环
        function startGameLoop() {
            if (animationFrameId) {
                cancelAnimationFrame(animationFrameId);
            }
            
            function gameLoop(timestamp) {
                // 更新帧率计数
                frames++;
                if (timestamp - startTime >= 1000) {
                    // 每秒更新一次FPS
                    const fps = Math.round(frames * 1000 / (timestamp - startTime));
                    console.log(`FPS: ${fps}`);
                    frames = 0;
                    startTime = timestamp;
                }
                
                // 清除画布
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                
                // 绘制基本棋盘
                drawBoard();
                
                // 绘制所有棋子
                drawAllPieces();
                
                // 绘制最后落子标记
                if (moveHistory.length > 0) {
                    const lastMove = moveHistory[moveHistory.length - 1];
                    drawLastMoveMarker(lastMove.x, lastMove.y);
                }
                
                // 更新并绘制粒子效果
                updateParticles();
                drawParticles();
                
                // 继续循环
                animationFrameId = requestAnimationFrame(gameLoop);
            }
            
            animationFrameId = requestAnimationFrame(gameLoop);
        }
        
        // 绘制棋盘
        function drawBoard() {
            // 绘制棋盘背景
            const gradient = ctx.createRadialGradient(
                BOARD_SIZE/2, BOARD_SIZE/2, BOARD_SIZE/10,
                BOARD_SIZE/2, BOARD_SIZE/2, BOARD_SIZE/1.5
            );
            gradient.addColorStop(0, '#E2C78C');
            gradient.addColorStop(1, '#D2B48C');
            
            ctx.fillStyle = gradient;
            ctx.fillRect(0, 0, BOARD_SIZE, BOARD_SIZE);
            
            // 绘制网格线
            ctx.strokeStyle = '#8B4513';
            ctx.lineWidth = 1;
            
            // 创建木纹效果
            for (let i = 0; i < GRID_SIZE; i++) {
                const variance = Math.sin(i * 0.2) * 0.5;
                ctx.strokeStyle = `rgba(139, 69, 19, ${0.6 + variance * 0.1})`;
                
                // 绘制水平线
                ctx.beginPath();
                ctx.moveTo(CELL_SIZE/2, i * CELL_SIZE + CELL_SIZE/2);
                ctx.lineTo(BOARD_SIZE - CELL_SIZE/2, i * CELL_SIZE + CELL_SIZE/2);
                ctx.stroke();
                
                // 绘制垂直线
                ctx.beginPath();
                ctx.moveTo(i * CELL_SIZE + CELL_SIZE/2, CELL_SIZE/2);
                ctx.lineTo(i * CELL_SIZE + CELL_SIZE/2, BOARD_SIZE - CELL_SIZE/2);
                ctx.stroke();
            }
            
            // 绘制天元和星位
            const starPoints = [
                {x: 3, y: 3}, {x: 11, y: 3}, {x: 3, y: 11}, {x: 11, y: 11}, {x: 7, y: 7},
                {x: 3, y: 7}, {x: 11, y: 7}, {x: 7, y: 3}, {x: 7, y: 11}
            ];
            
            starPoints.forEach(point => {
                ctx.beginPath();
                ctx.arc(
                    point.x * CELL_SIZE + CELL_SIZE/2,
                    point.y * CELL_SIZE + CELL_SIZE/2,
                    3, 0, Math.PI * 2
                );
                ctx.fillStyle = '#8B4513';
                ctx.fill();
            });
        }
        
        // 绘制所有棋子
        function drawAllPieces() {
            for (let x = 0; x < GRID_SIZE; x++) {
                for (let y = 0; y < GRID_SIZE; y++) {
                    if (board[x][y] !== 0) {
                        drawPiece(x, y, board[x][y]);
                    }
                }
            }
        }
        
        // 绘制单个棋子
        function drawPiece(x, y, player) {
            const centerX = x * CELL_SIZE + CELL_SIZE/2;
            const centerY = y * CELL_SIZE + CELL_SIZE/2;
            const radius = CELL_SIZE/2 - 2;
            
            // 光晕效果
            const glowRadius = radius + 2;
            const glowGradient = ctx.createRadialGradient(
                centerX, centerY, radius * 0.8,
                centerX, centerY, glowRadius
            );
            
            if (player === 1) { // 黑棋
                glowGradient.addColorStop(0, 'rgba(0, 0, 0, 1)');
                glowGradient.addColorStop(0.7, 'rgba(50, 50, 50, 1)');
                glowGradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
            } else { // 白棋
                glowGradient.addColorStop(0, 'rgba(255, 255, 255, 1)');
                glowGradient.addColorStop(0.7, 'rgba(220, 220, 220, 1)');
                glowGradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
            }
            
            ctx.beginPath();
            ctx.arc(centerX, centerY, glowRadius, 0, 2 * Math.PI);
            ctx.fillStyle = glowGradient;
            ctx.fill();
            
            // 主体棋子
            ctx.beginPath();
            ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
            
            const gradient = ctx.createRadialGradient(
                centerX - radius/3, centerY - radius/3, radius/10,
                centerX, centerY, radius
            );
            
            if (player === 1) { // 黑棋
                gradient.addColorStop(0, '#666');
                gradient.addColorStop(1, '#000');
            } else { // 白棋
                gradient.addColorStop(0, '#fff');
                gradient.addColorStop(0.8, '#eee');
                gradient.addColorStop(1, '#ccc');
            }
            
            ctx.fillStyle = gradient;
            ctx.fill();
            
            // 高光效果
            ctx.beginPath();
            const highlightRadius = radius * 0.25;
            ctx.arc(
                centerX - radius * 0.2,
                centerY - radius * 0.2,
                highlightRadius,
                0, 2 * Math.PI
            );
            
            const highlightGradient = ctx.createRadialGradient(
                centerX - radius * 0.2,
                centerY - radius * 0.2,
                0,
                centerX - radius * 0.2,
                centerY - radius * 0.2,
                highlightRadius
            );
            
            if (player === 1) { // 黑棋高光
                highlightGradient.addColorStop(0, 'rgba(255, 255, 255, 0.4)');
                highlightGradient.addColorStop(1, 'rgba(0, 0, 0, 0)');
            } else { // 白棋高光
                highlightGradient.addColorStop(0, 'rgba(255, 255, 255, 0.8)');
                highlightGradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
            }
            
            ctx.fillStyle = highlightGradient;
            ctx.fill();
        }

        function checkWin(x, y, player) {
            const directions = [
                [1, 0], // 水平
                [0, 1], // 垂直
                [1, 1], // 正对角线
                [1, -1] // 反对角线
            ];

            for (let [dx, dy] of directions) {
                let count = 1;
                for (let i = 1; i < 5; i++) {
                    const nx = x + dx * i;
                    const ny = y + dy * i;
                    if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE && board[nx][ny] === player) {
                        count++;
                    } else {
                        break;
                    }
                }
                for (let i = 1; i < 5; i++) {
                    const nx = x - dx * i;
                    const ny = y - dy * i;
                    if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE && board[nx][ny] === player) {
                        count++;
                    } else {
                        break;
                    }
                }
                if (count >= 5) {
                    return true;
                }
            }
            return false;
        }

        function checkDraw() {
            return board.every(row => row.every(cell => cell !== 0));
        }

        function handleClick(event) {
            if (gameOver) return;

            const rect = canvas.getBoundingClientRect();
            const x = Math.floor((event.clientX - rect.left) / CELL_SIZE);
            const y = Math.floor((event.clientY - rect.top) / CELL_SIZE);

            if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE && board[x][y] === 0) {
                board[x][y] = currentPlayer;
                moveHistory.push({ x, y, player: currentPlayer }); // 记录落子位置
                drawPiece(x, y, currentPlayer);

                if (checkWin(x, y, currentPlayer)) {
                    gameInfo.textContent = currentPlayer === 1 ? '黑棋获胜！' : '白棋获胜！';
                    gameOverMessage.textContent = currentPlayer === 1 ? '黑棋获胜！' : '白棋获胜！';
                    gameOverDialog.style.display = 'block';
                    gameOver = true;
                } else if (checkDraw()) {
                    gameInfo.textContent = '平局！';
                    gameOverMessage.textContent = '平局！';
                    gameOverDialog.style.display = 'block';
                    gameOver = true;
                } else {
                    currentPlayer = -currentPlayer;
                    gameInfo.textContent = currentPlayer === 1 ? '当前轮到黑棋' : '当前轮到白棋';
                }
            }
        }

        function resetGame() {
            board = Array.from({ length: GRID_SIZE }, () => Array(GRID_SIZE).fill(0));
            currentPlayer = 1;
            gameOver = false;
            moveHistory = [];
            gameInfo.textContent = '当前轮到黑棋';
            gameOverDialog.style.display = 'none';
            drawBoard();
        }

        function undoMove() {
            if (moveHistory.length === 0 || gameOver) return;

            const lastMove = moveHistory.pop();
            board[lastMove.x][lastMove.y] = 0;
            currentPlayer = lastMove.player;

            // 重绘棋盘
            drawBoard();
            moveHistory.forEach(move => drawPiece(move.x, move.y, move.player));

            gameInfo.textContent = currentPlayer === 1 ? '当前轮到黑棋' : '当前轮到白棋';
        }

        canvas.addEventListener('click', handleClick);
        window.addEventListener('keydown', (event) => {
            if (event.key === 'r' && gameOver) {
                resetGame();
            }
        });

        // 保存游戏
        function saveGame() {
            if (gameOver) return;
            
            const gameData = {
                board: board,
                currentPlayer: currentPlayer,
                moveHistory: moveHistory
            };
            
            try {
                localStorage.setItem('gomokuGame', JSON.stringify(gameData));
                
                // 显示保存成功提示
                const savedMessage = document.createElement('div');
                savedMessage.textContent = '游戏已保存';
                savedMessage.style.position = 'fixed';
                savedMessage.style.top = '20px';
                savedMessage.style.left = '50%';
                savedMessage.style.transform = 'translateX(-50%)';
                savedMessage.style.backgroundColor = 'rgba(0, 128, 0, 0.8)';
                savedMessage.style.color = 'white';
                savedMessage.style.padding = '10px 20px';
                savedMessage.style.borderRadius = '5px';
                savedMessage.style.zIndex = '1000';
                
                document.body.appendChild(savedMessage);
                
                setTimeout(() => {
                    document.body.removeChild(savedMessage);
                }, 2000);
            } catch (e) {
                console.error('保存游戏失败:', e);
            }
        }
        
        // 加载游戏
        function loadGame() {
            try {
                const gameData = JSON.parse(localStorage.getItem('gomokuGame'));
                
                if (!gameData) {
                    const noSaveMessage = document.createElement('div');
                    noSaveMessage.textContent = '没有找到保存的游戏';
                    noSaveMessage.style.position = 'fixed';
                    noSaveMessage.style.top = '20px';
                    noSaveMessage.style.left = '50%';
                    noSaveMessage.style.transform = 'translateX(-50%)';
                    noSaveMessage.style.backgroundColor = 'rgba(255, 0, 0, 0.8)';
                    noSaveMessage.style.color = 'white';
                    noSaveMessage.style.padding = '10px 20px';
                    noSaveMessage.style.borderRadius = '5px';
                    noSaveMessage.style.zIndex = '1000';
                    
                    document.body.appendChild(noSaveMessage);
                    
                    setTimeout(() => {
                        document.body.removeChild(noSaveMessage);
                    }, 2000);
                    
                    return;
                }
                
                board = gameData.board;
                currentPlayer = gameData.currentPlayer;
                moveHistory = gameData.moveHistory;
                gameOver = false;
                gameInfo.textContent = currentPlayer === 1 ? '当前轮到黑棋' : '当前轮到白棋';
                gameOverDialog.style.display = 'none';
                
                // 更新历史记录显示
                updateMoveHistory();
                
                // 显示加载成功提示
                const loadedMessage = document.createElement('div');
                loadedMessage.textContent = '游戏已加载';
                loadedMessage.style.position = 'fixed';
                loadedMessage.style.top = '20px';
                loadedMessage.style.left = '50%';
                loadedMessage.style.transform = 'translateX(-50%)';
                loadedMessage.style.backgroundColor = 'rgba(0, 128, 0, 0.8)';
                loadedMessage.style.color = 'white';
                loadedMessage.style.padding = '10px 20px';
                loadedMessage.style.borderRadius = '5px';
                loadedMessage.style.zIndex = '1000';
                
                document.body.appendChild(loadedMessage);
                
                setTimeout(() => {
                    document.body.removeChild(loadedMessage);
                }, 2000);
            } catch (e) {
                console.error('加载游戏失败:', e);
            }
        }
        
        // 检查是否有保存的游戏
        function checkSavedGame() {
            if (localStorage.getItem('gomokuGame')) {
                const loadButton = document.getElementById('loadButton');
                if (loadButton) {
                    loadButton.disabled = false;
                }
            }
        }
        
        // 粒子效果 - 创建粒子
        function generateParticles(x, y, player) {
            const particleCount = 20;
            const color = player === 1 ? '#000' : '#fff';
            
            for (let i = 0; i < particleCount; i++) {
                particles.push({
                    x: x,
                    y: y,
                    size: Math.random() * 4 + 1,
                    speedX: (Math.random() - 0.5) * 8,
                    speedY: (Math.random() - 0.5) * 8,
                    color: color,
                    alpha: 1,
                    rotation: Math.random() * 360,
                    life: 30 + Math.random() * 20
                });
            }
        }
        
        // 更新粒子状态
        function updateParticles() {
            for (let i = particles.length - 1; i >= 0; i--) {
                const p = particles[i];
                
                p.x += p.speedX;
                p.y += p.speedY;
                p.alpha -= 0.02;
                p.life -= 1;
                
                // 移除消失的粒子
                if (p.alpha <= 0 || p.life <= 0) {
                    particles.splice(i, 1);
                }
            }
        }
        
        // 绘制粒子
        function drawParticles() {
            particles.forEach(p => {
                ctx.save();
                ctx.globalAlpha = p.alpha;
                ctx.fillStyle = p.color;
                
                ctx.translate(p.x, p.y);
                ctx.rotate(p.rotation * Math.PI / 180);
                
                ctx.fillRect(-p.size / 2, -p.size / 2, p.size, p.size);
                
                ctx.restore();
            });
        }
        
        // 创建胜利特效
        function createVictoryEffect(x, y) {
            const centerX = x * CELL_SIZE + CELL_SIZE/2;
            const centerY = y * CELL_SIZE + CELL_SIZE/2;
            
            // 创建更多粒子
            for (let i = 0; i < 50; i++) {
                const angle = Math.random() * Math.PI * 2;
                const distance = Math.random() * 100 + 50;
                
                particles.push({
                    x: centerX,
                    y: centerY,
                    size: Math.random() * 6 + 2,
                    speedX: Math.cos(angle) * (Math.random() * 2 + 1),
                    speedY: Math.sin(angle) * (Math.random() * 2 + 1),
                    color: `hsl(${Math.random() * 360}, 100%, 50%)`,
                    alpha: 1,
                    rotation: Math.random() * 360,
                    life: 60 + Math.random() * 30
                });
            }
            
            // 创建光环效果
            for (let i = 0; i < 5; i++) {
                setTimeout(() => {
                    particles.push({
                        x: centerX,
                        y: centerY,
                        size: 100 + i * 30,
                        isRing: true,
                        color: `hsl(${i * 50}, 100%, 50%)`,
                        alpha: 1,
                        life: 30
                    });
                }, i * 100);
            }
        }
        
        // 绘制棋盘实时阴影效果
        function drawBoardShadow() {
            // 绘制棋盘阴影效果，随着时间变化
            const time = performance.now() / 1000;
            const shadowOffset = Math.sin(time) * 5 + 10;
            
            ctx.shadowColor = 'rgba(0, 0, 0, 0.3)';
            ctx.shadowBlur = shadowOffset;
            ctx.shadowOffsetX = shadowOffset;
            ctx.shadowOffsetY = shadowOffset;
            
            // 绘制完成后重置阴影
            ctx.shadowColor = 'transparent';
            ctx.shadowBlur = 0;
            ctx.shadowOffsetX = 0;
            ctx.shadowOffsetY = 0;
        }
        
        // 绘制最后落子标记
        function drawLastMoveMarker(x, y) {
            const centerX = x * CELL_SIZE + CELL_SIZE/2;
            const centerY = y * CELL_SIZE + CELL_SIZE/2;
            
            ctx.beginPath();
            ctx.arc(centerX, centerY, CELL_SIZE/6, 0, Math.PI * 2);
            ctx.strokeStyle = 'rgba(255, 0, 0, 0.6)';
            ctx.lineWidth = 2;
            ctx.stroke();
        }
        
        // 处理鼠标移动
        function handleMouseMove(event) {
            const rect = canvas.getBoundingClientRect();
            const scaleX = canvas.width / rect.width;
            const scaleY = canvas.height / rect.height;
            
            const x = Math.floor(((event.clientX - rect.left) * scaleX) / CELL_SIZE);
            const y = Math.floor(((event.clientY - rect.top) * scaleY) / CELL_SIZE);
            
            if (x >= 0 && x < GRID_SIZE && y >= 0 && y < GRID_SIZE) {
                const centerX = x * CELL_SIZE + CELL_SIZE/2;
                const centerY = y * CELL_SIZE + CELL_SIZE/2;
                
                positionMarker.style.display = 'block';
                positionMarker.style.left = `${centerX + canvas.offsetLeft}px`;
                positionMarker.style.top = `${centerY + canvas.offsetTop}px`;
                
                currentPosition = { x, y };
            } else {
                positionMarker.style.display = 'none';
            }
        }
        
        // 处理键盘输入
        function handleKeydown(event) {
            if (gameOver) {
                if (event.key === 'r' || event.key === 'R') {
                    resetGame();
                    return;
                }
            }
            
            if (currentPosition.x === -1) {
                currentPosition = { x: Math.floor(GRID_SIZE/2), y: Math.floor(GRID_SIZE/2) };
            }
            
            switch(event.key) {
                case 'ArrowUp':
                    currentPosition.y = Math.max(0, currentPosition.y - 1);
                    updatePositionMarker();
                    event.preventDefault();
                    break;
                case 'ArrowDown':
                    currentPosition.y = Math.min(GRID_SIZE - 1, currentPosition.y + 1);
                    updatePositionMarker();
                    event.preventDefault();
                    break;
                case 'ArrowLeft':
                    currentPosition.x = Math.max(0, currentPosition.x - 1);
                    updatePositionMarker();
                    event.preventDefault();
                    break;
                case 'ArrowRight':
                    currentPosition.x = Math.min(GRID_SIZE - 1, currentPosition.x + 1);
                    updatePositionMarker();
                    event.preventDefault();
                    break;
                case 'Enter':
                case ' ':
                    if (currentPosition.x !== -1 && !gameOver) {
                        placePiece(currentPosition.x, currentPosition.y);
                    }
                    event.preventDefault();
                    break;
                case 'z':
                case 'Z':
                    if (event.ctrlKey || event.metaKey) {
                        undoMove();
                        event.preventDefault();
                    }
                    break;
            }
        }
        
        // 更新位置标记
        function updatePositionMarker() {
            if (currentPosition.x !== -1) {
                const centerX = currentPosition.x * CELL_SIZE + CELL_SIZE/2;
                const centerY = currentPosition.y * CELL_SIZE + CELL_SIZE/2;
                
                positionMarker.style.display = 'block';
                positionMarker.style.left = `${centerX + canvas.offsetLeft}px`;
                positionMarker.style.top = `${centerY + canvas.offsetTop}px`;
            }
        }
        
        // 放置棋子
        function placePiece(x, y) {
            if (x < 0 || x >= GRID_SIZE || y < 0 || y >= GRID_SIZE || board[x][y] !== 0 || gameOver) {
                return;
            }
            
            // 更新棋盘
            board[x][y] = currentPlayer;
            
            // 播放落子音效
            moveSound.currentTime = 0;
            moveSound.play().catch(e => console.log("音频播放失败:", e));
            
            // 添加落子记录
            const moveNumber = moveHistory.length + 1;
            const notation = String.fromCharCode(65 + x) + (y + 1);
            moveHistory.push({ x, y, player: currentPlayer, notation, moveNumber });
            
            // 更新历史记录显示
            updateMoveHistory();
            
            // 检查胜负
            if (checkWin(x, y, currentPlayer)) {
                gameInfo.textContent = currentPlayer === 1 ? '黑棋获胜！' : '白棋获胜！';
                gameOverMessage.textContent = currentPlayer === 1 ? '黑棋获胜！' : '白棋获胜！';
                gameOverDialog.style.display = 'block';
                gameOver = true;
                
                // 播放胜利音效
                winSound.currentTime = 0;
                winSound.play().catch(e => console.log("音频播放失败:", e));
            } else if (checkDraw()) {
                gameInfo.textContent = '平局！';
                gameOverMessage.textContent = '平局！';
                gameOverDialog.style.display = 'block';
                gameOver = true;
            } else {
                // 切换玩家
                currentPlayer = -currentPlayer;
                gameInfo.textContent = currentPlayer === 1 ? '当前轮到黑棋' : '当前轮到白棋';
            }
        }
        
        // 检查胜利
        function checkWin(x, y, player) {
            const directions = [
                [1, 0],  // 水平
                [0, 1],  // 垂直
                [1, 1],  // 正对角线
                [1, -1]  // 反对角线
            ];
            
            for (let [dx, dy] of directions) {
                let count = 1;
                
                // 正向检查
                for (let i = 1; i < 5; i++) {
                    const nx = x + dx * i;
                    const ny = y + dy * i;
                    if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE && board[nx][ny] === player) {
                        count++;
                    } else {
                        break;
                    }
                }
                
                // 反向检查
                for (let i = 1; i < 5; i++) {
                    const nx = x - dx * i;
                    const ny = y - dy * i;
                    if (nx >= 0 && nx < GRID_SIZE && ny >= 0 && ny < GRID_SIZE && board[nx][ny] === player) {
                        count++;
                    } else {
                        break;
                    }
                }
                
                if (count >= 5) {
                    return true;
                }
            }
            
            return false;
        }
        
        // 检查平局
        function checkDraw() {
            return board.every(row => row.every(cell => cell !== 0));
        }
        
        // 悔棋
        function undoMove() {
            if (moveHistory.length === 0 || gameOver) {
                return;
            }
            
            const lastMove = moveHistory.pop();
            board[lastMove.x][lastMove.y] = 0;
            currentPlayer = lastMove.player;
            
            // 更新历史记录显示
            updateMoveHistory();
            
            // 更新游戏状态
            gameInfo.textContent = currentPlayer === 1 ? '当前轮到黑棋' : '当前轮到白棋';
            
            // 移除游戏结束对话框
            if (gameOver) {
                gameOver = false;
                gameOverDialog.style.display = 'none';
            }
        }
        
        // 重置游戏
        function resetGame() {
            board = Array.from({ length: GRID_SIZE }, () => Array(GRID_SIZE).fill(0));
            currentPlayer = 1;
            gameOver = false;
            moveHistory = [];
            gameInfo.textContent = '当前轮到黑棋';
            gameOverDialog.style.display = 'none';
        }
        
        // 更新移动历史记录
        function updateMoveHistory() {
            const historyContainer = document.getElementById('moveHistory');
            moveList.innerHTML = '';
            
            if (moveHistory.length === 0) {
                historyContainer.style.display = 'none';
                return;
            }
            
            historyContainer.style.display = 'block';
            
            moveHistory.forEach(move => {
                const moveElement = document.createElement('div');
                moveElement.className = 'history-move';
                moveElement.textContent = `${move.moveNumber}. ${move.player === 1 ? '黑' : '白'} ${move.notation}`;
                moveList.appendChild(moveElement);
            });
            
            // 滚动到最新记录
            moveList.scrollTop = moveList.scrollHeight;
        }
        
        // 初始化游戏
        window.addEventListener('DOMContentLoaded', init);
    </script>
</body>
</html>